package com.example.music.utility;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * @author jing
 * @version 1.0
 * @desc RSA
 * @date 2021/9/10 0010 10:20
 **/
public class RSAUtils {

    private final static String ASYMMETRIC_ALGORITHM = "RSA/None/PKCS1Padding";

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 初始化key pair
     *
     * @return KeyPair
     */
    private static KeyPair genrateKey() {
        try {
            // 随机数用于安全加密
            SecureRandom random = new SecureRandom();
            // 初始化秘钥
            KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME);
            generator.initialize(2048, random);
            return generator.generateKeyPair();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 解密数据
     *
     * @param arg           需要解密的字符串
     * @param privateKeyStr base64加密的秘钥
     * @return 解密后的字符串
     */
    public static String decryptBase64(String arg, String privateKeyStr) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(privateKeyStr);
        // 初始化私钥
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        // 进行解密
        return decryptBase64(arg, privateKey);
    }

    /**
     * 解密数据
     *
     * @param arg 需要解密的字符串
     * @return 解密后的字符串
     */
    public static String decryptBase64(String arg, PrivateKey privateKey) throws Exception {
        // Cipher 提供加密和解密功能
        Cipher cipher = Cipher.getInstance(ASYMMETRIC_ALGORITHM, BouncyCastleProvider.PROVIDER_NAME);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        // 解密数据
        byte[] plainText = cipher.doFinal(Base64.getDecoder().decode(arg));
        return new String(plainText);
    }

    /**
     * 加密数据
     *
     * @param arg       需要解密的字符串
     * @param pubKeyStr 公钥base64编码后
     * @return 解密后的字符串
     */
    public static String encryptBase64(String arg, String pubKeyStr) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(pubKeyStr);
        // 初始化公钥
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
        return encryptBase64(arg, publicKey);
    }


    /**
     * @param arg       待加密数据字节数
     * @param publicKey 公钥
     * @return 加密后数据
     */
    public static String encryptBase64(String arg, PublicKey publicKey) throws Exception {
        Provider provider = new BouncyCastleProvider();
        Security.addProvider(provider);
        Cipher cipher = Cipher.getInstance(ASYMMETRIC_ALGORITHM, provider);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encrypt = cipher.doFinal(arg.getBytes());
        return Base64.getEncoder().encodeToString(encrypt);
    }


    public static void main(String[] args) throws Exception {
        KeyPair keyPair = genrateKey();
        String privateKeyStr = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
        String publicKeyStr = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
        System.out.println(String.format("privateKey: %s", privateKeyStr));
        System.out.println(String.format("publicKey: %s", publicKeyStr));
        String content = "abcde";
        String cipherText = encryptBase64(content, publicKeyStr);
        String decryptText = decryptBase64(cipherText, privateKeyStr);
        System.out.println(String.format("解密数据：%s", decryptText));
    }
}
